/*
 * NISTMessenger.java
 *
 * Created on January 27, 2004, 6:53 PM
 */

package gov.nist.applet.phone.ua.gui;

import gov.nist.applet.phone.media.messaging.VoiceRecorder;
import gov.nist.applet.phone.ua.ChatSessionManager;
import gov.nist.applet.phone.ua.Configuration;
import gov.nist.applet.phone.ua.MessengerController;
import gov.nist.applet.phone.ua.MessengerManager;
import gov.nist.applet.phone.ua.RegisterStatus;
import gov.nist.applet.phone.ua.StopMessenger;
import gov.nist.applet.phone.ua.presence.Subscriber;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.URL;

import javax.swing.ButtonGroup;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

/**
 * This application has been designed in following the MVC design pattern Thus,
 * this class is part of the View.
 * 
 * @author Jean Deruelle
 * 
 *         <a href="{@docRoot} /uncopyright.html">This code is in the public
 *         domain.</a>
 */
public class NISTMessenger extends javax.swing.JFrame implements
		java.util.Observer, NISTMessengerGUI {
	Configuration configuration;
	/* MVC attributes */
	private MessengerManager sipMeetingManager;
	private MessengerController controllerMeeting;
	private ChatSessionManager chatSessionManager;
	private ServerInfoXmlManager serverInfoManager;
	private String path = "xmlSource/ServerInfo.xml";

	/** Creates new form NISTMessenger */
	public NISTMessenger() {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
			SwingUtilities.updateComponentTreeUI(this);
		} catch (Exception exe) {
			exe.printStackTrace();
		}
		configuration = new Configuration();
		serverInfoManager = new ServerInfoXmlManager(path);
		chatSessionManager = new ChatSessionManager();
		sipMeetingManager = new MessengerManager(configuration, this);
		sipMeetingManager.addObserver(this);
		controllerMeeting = new MessengerController(sipMeetingManager,
				chatSessionManager, this);
		initComponents();
		listModel = new DefaultListModel();

		// Create the list and put it in a scroll pane.
		jList1 = new JList(listModel);
		jList1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		jList1.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				if (e.getClickCount() == 2) {
					String contactAddress = (String) listModel.elementAt(jList1
							.getSelectedIndex());
					if (contactAddress.trim().indexOf('(') != -1)
						contactAddress = contactAddress.substring(0,
								contactAddress.trim().indexOf("("));
					// check if a chat frame has already been opened
					ChatFrame chatFrame = (ChatFrame) chatSessionManager
							.getChatFrame(contactAddress);
					if (chatFrame == null) {
						// emulate button click
						chatFrame = new ChatFrame(this, contactAddress,
								sipMeetingManager, chatSessionManager);
						chatSessionManager.addChatSession(contactAddress,
								chatFrame);
						chatFrame.show();
					} else {
						chatFrame.show();
					}
				}
			}
		});

		JScrollPane listScrollPane = new JScrollPane(jList1);
		listScrollPane.setBounds(30, 100, 250, 150);
		mainPanel.add(listScrollPane);
		getContentPane().add(mainPanel);
		// Get current classloader
		ClassLoader cl = this.getClass().getClassLoader();
		URL url = cl.getResource("images/short_nisthome_banner.jpg");
		if (url != null)
			imageLabel.setIcon(new ImageIcon(url));
		this.pack();
		this.setTitle("SIP Phone");
		this.setSize(320, 520);
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	private void initComponents() {// GEN-BEGIN:initComponents
		mainPanel = new javax.swing.JPanel();
		imageLabel = new javax.swing.JLabel();
		addContactButton = new javax.swing.JButton();
		removeContactButton = new javax.swing.JButton();
		jLabel1 = new javax.swing.JLabel();
		fileMenuBar1 = new javax.swing.JMenuBar();
		jMenu5 = new javax.swing.JMenu();
		jMenuItemConfiguration = new javax.swing.JMenuItem();
		jMenuItemRegister = new javax.swing.JMenuItem();
		jMenuItemUnregister = new javax.swing.JMenuItem();
		jMenuItemExit = new javax.swing.JMenuItem();
		jMenuStatus = new javax.swing.JMenu();
		showConnectionButton = new javax.swing.JButton(new ImageIcon(
				"images/left.jpg"));
		connectionFrame = null;
		onlineJRadioButtonMenuItem = new JRadioButtonMenuItem("Online");
		awayJRadioButtonMenuItem = new JRadioButtonMenuItem("Away");
		offlineJRadioButtonMenuItem = new JRadioButtonMenuItem("Be Right Back");
		busyJRadioButtonMenuItem = new JRadioButtonMenuItem("Busy");

		getContentPane().setLayout(null);

		addWindowListener(new java.awt.event.WindowAdapter() {
			public void windowClosing(java.awt.event.WindowEvent evt) {
				exitForm(evt);
			}
		});

		mainPanel.setLayout(null);

		mainPanel.setMinimumSize(new java.awt.Dimension(310, 500));
		mainPanel.setPreferredSize(new java.awt.Dimension(310, 500));
		imageLabel.setMaximumSize(new java.awt.Dimension(400, 50));
		imageLabel.setMinimumSize(new java.awt.Dimension(300, 50));
		imageLabel.setPreferredSize(new java.awt.Dimension(400, 50));
		mainPanel.add(imageLabel);
		imageLabel.setBounds(30, 0, 250, 50);

		showConnectionButton.setOpaque(false);
		showConnectionButton
				.addActionListener(new java.awt.event.ActionListener() {
					public void actionPerformed(java.awt.event.ActionEvent evt) {
						showConnectionButtonActionPerformed(evt);
					}
				});
		showConnectionButton.setBounds(280, 0, 30, 50);
		mainPanel.add(showConnectionButton);

		addContactButton.setText("Add Contact");
		addContactButton.setOpaque(false);
		addContactButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				addContactButtonActionPerformed(evt);
			}
		});

		mainPanel.add(addContactButton);
		addContactButton.setBounds(10, 400, 120, 40);

		removeContactButton.setText("Remove Contact");
		removeContactButton.setEnabled(false);
		removeContactButton
				.addActionListener(new java.awt.event.ActionListener() {
					public void actionPerformed(java.awt.event.ActionEvent evt) {
						removeContactButtonActionPerformed(evt);
					}
				});

		mainPanel.add(removeContactButton);
		removeContactButton.setBounds(160, 400, 130, 40);

		jLabel1.setText("Not Logged");
		mainPanel.add(jLabel1);
		jLabel1.setOpaque(true);
		jLabel1.setBackground(new Color(204, 255, 204));
		jLabel1.setBounds(30, 50, 250, 50);

		getContentPane().add(mainPanel);
		mainPanel.setBounds(0, 0, 310, 500);

		jMenu5.setText("Menu");
		jMenuItemConfiguration.setText("Configuration");
		jMenuItemConfiguration
				.addActionListener(new java.awt.event.ActionListener() {
					public void actionPerformed(java.awt.event.ActionEvent evt) {
						jMenuItemConfigurationActionPerformed(evt);
					}
				});

		jMenu5.add(jMenuItemConfiguration);

		jMenuItemRegister.setText("Register");
		jMenuItemRegister
				.addActionListener(new java.awt.event.ActionListener() {
					public void actionPerformed(java.awt.event.ActionEvent evt) {
						jMenuItemRegisterActionPerformed(evt);
					}
				});

		jMenu5.add(jMenuItemRegister);

		jMenuItemUnregister.setText("Unregister");
		jMenuItemUnregister
				.addActionListener(new java.awt.event.ActionListener() {
					public void actionPerformed(java.awt.event.ActionEvent evt) {
						jMenuItemUnregisterActionPerformed(evt);
					}
				});

		jMenu5.add(jMenuItemUnregister);

		jMenuStatus.setText("Status");
		onlineJRadioButtonMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				onlineActionPerformed(evt);
			}
		});

		awayJRadioButtonMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				awayActionPerformed(evt);
			}
		});

		offlineJRadioButtonMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				beRightBackActionPerformed(evt);
			}
		});

		busyJRadioButtonMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				busyActionPerformed(evt);
			}
		});
		statusGroup = new ButtonGroup();
		onlineJRadioButtonMenuItem.setSelected(true);
		statusGroup.add(onlineJRadioButtonMenuItem);
		statusGroup.add(offlineJRadioButtonMenuItem);
		statusGroup.add(busyJRadioButtonMenuItem);
		statusGroup.add(awayJRadioButtonMenuItem);

		jMenuStatus.add(awayJRadioButtonMenuItem);
		jMenuStatus.add(onlineJRadioButtonMenuItem);
		jMenuStatus.add(offlineJRadioButtonMenuItem);
		jMenuStatus.add(busyJRadioButtonMenuItem);

		jMenu5.add(jMenuStatus);

		jMenuItemExit.setText("Exit");
		jMenuItemExit.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				jMenuItemExitActionPerformed(evt);
			}
		});

		jMenu5.add(jMenuItemExit);

		fileMenuBar1.add(jMenu5);

		setJMenuBar(fileMenuBar1);

		this.setBounds(300, 200, 320, 520);

		pack();
	}// GEN-END:initComponents

	private void showConnectionButtonActionPerformed(ActionEvent evt) {
		// TODO Auto-generated method stub
		if (connectionFrame == null) {
			int x = this.getX() + this.getWidth();
			int y = this.getY();
			connectionFrame = new ConnectionFrame(x, y, this.getWidth(), this
					.getHeight(), this, this.serverInfoManager);
		}
		if (connectionFrame.isVisible()) {
			showConnectionButton.setIcon(new ImageIcon("images/left.jpg"));
			connectionFrame.setVisible(false);
		} else {
			showConnectionButton.setIcon(new ImageIcon("images/right.jpg"));
			connectionFrame.setVisible(true);
		}
	}

	private void jMenuItemExitActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItemExitActionPerformed
		// Add your handling code here:
		close();
	}// GEN-LAST:event_jMenuItemExitActionPerformed

	private void jMenuItemUnregisterActionPerformed(
			java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItemUnregisterActionPerformed
		// Add your handling code here:
		if (sipMeetingManager.getRegisterStatus().equalsIgnoreCase(
				RegisterStatus.NOT_REGISTERED)) {
			JOptionPane
					.showMessageDialog(
							this,
							"You are currently not registered, please register to un-register",
							"Already un-registered", JOptionPane.ERROR_MESSAGE);
			return;
		}
		unRegister();
		controllerMeeting.undisplayAllContact();
		removeContactButton.setEnabled(false);
	}// GEN-LAST:event_jMenuItemUnregisterActionPerformed

	private void jMenuItemRegisterActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItemRegisterActionPerformed
		// Add your handling code here:
		if (sipMeetingManager.getRegisterStatus().equalsIgnoreCase(
				RegisterStatus.REGISTERED)) {
			JOptionPane.showMessageDialog(this,
					"You are already registered, please un-register before",
					"Already registered", JOptionPane.ERROR_MESSAGE);
			return;
		}
		sipMeetingManager.register();
		controllerMeeting.displayAllContact();
		removeContactButton.setEnabled(true);
	}// GEN-LAST:event_jMenuItemRegisterActionPerformed

	private void jMenuItemConfigurationActionPerformed(
			java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItemConfigurationActionPerformed
		// Add your handling code here:
		new ConfigurationFrame(sipMeetingManager).show();
	}// GEN-LAST:event_jMenuItemConfigurationActionPerformed

	private void onlineActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItemRegisterActionPerformed
		// Add your handling code here:
		jLabel1.setText("Logged as : " + configuration.userURI + " - Online");
		sipMeetingManager.getPresentityManager().sendNotifyToAllSubscribers(
				"open", "online");
	}// GEN-LAST:event_jMenuItemRegisterActionPerformed

	private void busyActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItemRegisterActionPerformed
		// Add your handling code here:
		jLabel1.setText("Logged as : " + configuration.userURI + " - Busy");
		sipMeetingManager.getPresentityManager().sendNotifyToAllSubscribers(
				"inuse", "busy");
	}// GEN-LAST:event_jMenuItemRegisterActionPerformed

	private void awayActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItemRegisterActionPerformed
		// Add your handling code here:
		jLabel1.setText("Logged as : " + configuration.userURI + " - Away");
		sipMeetingManager.getPresentityManager().sendNotifyToAllSubscribers(
				"inactive", "away");
	}// GEN-LAST:event_jMenuItemRegisterActionPerformed

	private void beRightBackActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItemRegisterActionPerformed
		// Add your handling code here:
		jLabel1.setText("Logged as : " + configuration.userURI
				+ " - Be Right Back");
		sipMeetingManager.getPresentityManager().sendNotifyToAllSubscribers(
				"inactive", "berightback");
	}// GEN-LAST:event_jMenuItemRegisterActionPerformed

	private void removeContactButtonActionPerformed(
			java.awt.event.ActionEvent evt) {// GEN-FIRST:event_removeContactButtonActionPerformed
		controllerMeeting.removeContact();
	}// GEN-LAST:event_removeContactButtonActionPerformed

	private void addContactButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_addContactButtonActionPerformed
		// Add your handling code here:
		if (!sipMeetingManager.getRegisterStatus().equalsIgnoreCase(
				RegisterStatus.REGISTERED)) {
			JOptionPane.showMessageDialog(this,
					"You must be registered to add a new contact",
					"Contact Error", JOptionPane.ERROR_MESSAGE);
			return;
		}
		String contactAddress = (String) JOptionPane.showInputDialog(this,
				"Enter the contact address to add:\n", "Add Contact",
				JOptionPane.PLAIN_MESSAGE, null, null, null);
		System.out.println(contactAddress);
		if (contactAddress != null) {
			if (contactAddress.trim().matches("\\d+")) {
				contactAddress += "@"
						+ serverInfoManager.getInfo("proxyaddress");
				Subscriber subscriber = new Subscriber(contactAddress);
				sipMeetingManager.getPresentityManager().addSubscriber(
						subscriber);
				sipMeetingManager.sendSubscribe(contactAddress);
				controllerMeeting.addContact(contactAddress);
			} else {
				JOptionPane.showMessageDialog(this,
						"The contact must be of the form user@domain"
								+ ", the contact has not been added",
						"Contact Error", JOptionPane.ERROR_MESSAGE);
			}
		}
	}// GEN-LAST:event_addContactButtonActionPerformed

	/**
	 * Get the view component representing the logged status label
	 * 
	 * @return the logged status label
	 */
	public JLabel getLoggedStatusLabel() {
		return jLabel1;
	}

	/**
	 * Get the contact list from this frame
	 * 
	 * @return the contact list from this frame
	 */
	public JList getContactList() {
		return jList1;
	}

	/**
	 * Get the contact list from this frame
	 * 
	 * @return the contact list from this frame
	 */
	public JButton getRemoveContactButton() {
		return removeContactButton;
	}

	/**
     * 
     */
	public void update(java.util.Observable o, Object arg) {

	}

	/**
	 * Exit the Application
	 */
	private void exitForm(java.awt.event.WindowEvent evt) {// GEN-FIRST:event_exitForm
		close();
	}// GEN-LAST:event_exitForm

	/**
     * 
     *
     */
	private void close() {
		unRegister();
		if (!VoiceRecorder.isClosed())
			VoiceRecorder.getInstance().close();
		new StopMessenger(sipMeetingManager.getMessageListener());
		System.exit(0);
	}

	/**
     * 
     *
     */
	protected void unRegister() {
		if (sipMeetingManager.getRegisterStatus().equalsIgnoreCase(
				RegisterStatus.REGISTERED)) {
			if (chatSessionManager.hasActiveSessions()) {
				int response = javax.swing.JOptionPane
						.showConfirmDialog(
								null,
								" All current sessions will be closed,\n"
										+ " do you still want to close the application ?",
								"Close the Application",
								javax.swing.JOptionPane.YES_NO_OPTION,
								javax.swing.JOptionPane.QUESTION_MESSAGE);
				if (response == javax.swing.JOptionPane.NO_OPTION)
					return;
				else if (response == javax.swing.JOptionPane.YES_OPTION) {
					chatSessionManager.closeAllSessions();
				}
			}
			sipMeetingManager.unRegister();
		}
	}

	/**
	 * Fatal error.
	 */
	public void fatalError(String errorText) {
		JOptionPane.showMessageDialog(this, errorText, "Fatal Error",
				JOptionPane.ERROR_MESSAGE);
		close();
	}

	/**
	 * @param args
	 *            the command line arguments
	 */
	public static void main(String args[]) {
		new NISTMessenger().show();
	}

	/**
	 * GUI variables.
	 */
	// Variables declaration - do not modify//GEN-BEGIN:variables
	private javax.swing.JButton addContactButton;
	private javax.swing.JMenuBar fileMenuBar1;
	private javax.swing.JLabel imageLabel;
	private javax.swing.JLabel jLabel1;
	private javax.swing.JMenu jMenu5;
	private javax.swing.JMenuItem jMenuItemConfiguration;
	private javax.swing.JMenuItem jMenuItemRegister;
	private javax.swing.JMenuItem jMenuItemUnregister;
	private javax.swing.JMenuItem jMenuItemExit;
	private javax.swing.JMenu jMenuStatus;
	private javax.swing.JPanel mainPanel;
	private javax.swing.JButton removeContactButton;
	// End of variables declaration//GEN-END:variables
	private javax.swing.JList jList1;
	private DefaultListModel listModel;
	private JRadioButtonMenuItem onlineJRadioButtonMenuItem;
	private JRadioButtonMenuItem awayJRadioButtonMenuItem;
	private JRadioButtonMenuItem offlineJRadioButtonMenuItem;
	private JRadioButtonMenuItem busyJRadioButtonMenuItem;
	ButtonGroup statusGroup;
	private javax.swing.JButton showConnectionButton;
	private ConnectionFrame connectionFrame;

	public MessengerManager getSipMeetingManager() {
		return sipMeetingManager;
	}

	public MessengerController getControllerMeeting() {
		return controllerMeeting;
	}

}
